/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.p4;

import java.util.ArrayList;

import com.example.p4.R;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.os.Bundle;
import android.widget.TextView;

/**
 * SnakeView: implementation of a simple game of Snake
 */
@TargetApi(5)
public class MazeView extends MazeTileView {
	
    public static final int MODE_RUNNING = 1;
    public static final int MODE_WIN = 2;
    public static final int MODE_LOSE = 3;
    
    //Current game mode
    public int mode = MODE_RUNNING;

    private static final int WALL_BLOCK = 1;
    private static final int START_BLOCK = 2;
    private static final int WIN_BLOCK = 3;
    private static final int TIME_BAR = 4;
    private static final int TIME_BAR_BACK = 5;
    private static final int WIN = 6;
    private static final int LOSE = 7;

    //Number of maze levels deep
    protected static int numOfLevels = 4;
    
    //Level height in tiles
    protected int levelHeight = 0;
    
    //Current depth of player's mouse
    protected int currentLevel = 0;
    
    //Last valid point that the user "touched"
    protected Coordinate lastValidPoint = new Coordinate(0,0);
    
    //Progress Bar Images
    protected Drawable progressBar;
    protected Drawable progressBarBack;
    
    //Time left in game
    
    
    public double progressBarPercent = 0;
    /**
     * mScore: used to track the number of apples captured mMoveDelay: number of
     * milliseconds between snake movements. This will decrease as apples are
     * captured.
     */
    long mScore = 0;
    /**
     * mStatusText: text shows to the user in some run states
     */
    TextView mStatusText;

    /**
     * mSnakeTrail: a list of Coordinates that make up the snake's body
     * mAppleList: the secret location of the juicy apples the snake craves.
     */
    protected ArrayList<Coordinate> touchTrail = new ArrayList<Coordinate>();
    protected ArrayList<Coordinate> wallTrail = new ArrayList<Coordinate>();

    /**
     * Constructs a SnakeView based on inflation from XML
     */
    public MazeView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initSnakeView();
   }

    public MazeView(Context context, AttributeSet attrs, int defStyle) {
    	super(context, attrs, defStyle);
    	initSnakeView();
    }

    void initSnakeView() {
        setFocusable(true);
    }
    
    private void initTiles()
    {
    	Log.d("Init", "start of initTiles");
    	
    	
    	 resetTiles(8);
    	 Resources r = this.getContext().getResources();
         loadTile(WALL_BLOCK,         r.getDrawable(R.drawable.maze_floor_block));
         loadSizedTile(START_BLOCK,   r.getDrawable(R.drawable.maze_start_here), mTileSize*(levelHeight-1), mTileSize*(levelHeight-1));
         loadSizedTile(WIN_BLOCK,     r.getDrawable(R.drawable.maze_win),        mTileSize*(mXTileCount-2), mTileSize* (mYTileCount - ((numOfLevels-1)*levelHeight)-2));
         loadSizedTile(TIME_BAR,      r.getDrawable(R.drawable.progressbar),     screenWidth, 70);
         loadSizedTile(TIME_BAR_BACK, r.getDrawable(R.drawable.bright),          screenWidth, 70);
         loadSizedTile(WIN,           r.getDrawable(R.drawable.checkmark),       screenWidth, screenHeight);
         loadSizedTile(LOSE,          r.getDrawable(R.drawable.xmark),           screenWidth, screenHeight);
         
         Log.d("Init", "Creating progressBars");
         progressBar = (r.getDrawable(R.drawable.progressbar));
         progressBarBack = (r.getDrawable(R.drawable.bright));
         
         Log.d("Init", "Setting Bounds");
         progressBar.setBounds(0, screenHeight-mYOffset, screenWidth, screenHeight+70-mYOffset);
         progressBarBack.setBounds(0, screenHeight-mYOffset, screenWidth, screenHeight+70-mYOffset);
    }

    void initNewGame() {
    	setFocusable(true);
        wallTrail.clear();
        touchTrail.clear();

        // For now we're just going to load up a short default eastbound snake
        // that's just turned north
        
        levelHeight = mYTileCount / numOfLevels;
        int xOffset = mXTileCount / 4;
        
        for(int i=0; i<numOfLevels-1; i++)
        {
        	if(i%2 == 0)
        	{
        		for(int j=0; j<mXTileCount-xOffset; j++)
            		wallTrail.add(new Coordinate(j, (i+1)*levelHeight));
        	}
        	else
        	{
        		for(int j=xOffset; j<mXTileCount; j++)
            		wallTrail.add(new Coordinate(j, (i+1)*levelHeight));
        	}
        }
        
        for (int x = 0; x < mXTileCount; x++) {
        	wallTrail.add(new Coordinate(x, 0));
        	wallTrail.add(new Coordinate(x, mYTileCount-1));
        }
        for (int y = 1; y < mYTileCount - 1; y++) {
        	wallTrail.add(new Coordinate(0, y));
        	wallTrail.add(new Coordinate(mXTileCount-1, y));
        }
        
        initTiles();
        	
        mScore = 0;
    }
    
    void onWallCollision()
    {
    	touchTrail.clear();
    	currentLevel = 0;
    	lastValidPoint = new Coordinate(0,0);
    }
    
    void resetGame()
    {
    	reset();
    	mode = MODE_RUNNING;
    	touchTrail = new ArrayList<Coordinate>();
    	wallTrail = new ArrayList<Coordinate>();
    	currentLevel = 0;
    	lastValidPoint = new Coordinate(0,0);
    	progressBarPercent = 0;
    	Log.d("GameEvent", "Resetting game");
    }

    /**
     * Save game state so that the user does not lose anything
     * if the game process is killed while we are in the 
     * background.
     * 
     * @return a Bundle with this view's state
     */
    public Bundle saveState() {
        Bundle map = new Bundle();
        map.putLong("mScore", Long.valueOf(mScore));
        return map;
    }

    /**
     * Restore game state if our process is being relaunched
     * 
     * @param icicle a Bundle containing the game state
     */
    
    
    public boolean inStartArea(int x, int y)
    {
    	return (x > 0 && x <= levelHeight && y > 0 && y <= levelHeight);
    }
    
    void checkWallCollision()
    {
    	if(touchTrail.size() == 0)
    		return;
    	for(int i=0; i<wallTrail.size(); i++)
    	{
    		if(wallTrail.get(i).equals(touchTrail.get(touchTrail.size()-1)))
    		{
    			onWallCollision();
    			break;
    		}
    	}
    }
    
    void updateTrail()
    {
    	if(touchTrail.size() == 0)
    		return;
    	
    	lastValidPoint = touchTrail.get(touchTrail.size()-1);
    	
    	currentLevel = lastValidPoint.y / levelHeight;
    }
    
    /*
     * handles key events in the game. Update the direction our snake is traveling
     * based on the DPAD. Ignore events that would cause the snake to immediately
     * turn back on itself.
     * 
     * @see android.view.View#onKeyDown(int, android.os.KeyEvent)
     */
    

    /**
     * Sets the TextView that will be used to give information (such as "Game
     * Over" to the user.
     * 
     * @param newView
     */
    public void setTextView(TextView newView) {
        mStatusText = newView;
    }
    
    void updateStaticImages()
    {
    	setTile(START_BLOCK,   2, 1);
    	setTile(WIN_BLOCK,     1, (levelHeight*(numOfLevels-1))+1);
    }

    void updateMazeWalls() {
        for (int i = 0; i < wallTrail.size(); i++) {
            setTile(WALL_BLOCK, wallTrail.get(i).x, wallTrail.get(i).y);
        }
    }
    
    public void drawProgressBar(Canvas canvas)
    {
    	paint.setColor(Color.DKGRAY);
        if(progressBarBack != null){
        	progressBarBack.draw(canvas);
        	
        	Rect rect = progressBarBack.getBounds();
        	int barWidth = (int)(screenWidth*.92);
        	canvas.drawRect((float) ((barWidth - (barWidth*progressBarPercent))), rect.top, rect.right, rect.bottom, paint);
        }
        if(progressBar != null)
        	progressBar.draw(canvas);
    }
    
    @Override
    public void onDraw(Canvas canvas) {
    	paint.setColor(Color.GREEN);
    	
    	if(currentLevel%2 == 0)
    		canvas.drawRect(mXOffset, mYOffset+mTileSize * currentLevel * levelHeight, mXOffset + mTileSize * lastValidPoint.x, mYOffset+mTileSize * (currentLevel+1) * levelHeight, paint);
    	else
    		canvas.drawRect(mTileSize * lastValidPoint.x, mYOffset+mTileSize * currentLevel * levelHeight, mXOffset +mTileSize*mXTileCount, mYOffset+ mTileSize * (currentLevel+1) * levelHeight, paint);
        canvas.drawRect(mXOffset, mYOffset, mXOffset+mTileSize * mXTileCount, mYOffset + mTileSize + mTileSize * currentLevel * levelHeight, paint);
        
        drawProgressBar(canvas);
        
        super.onDraw(canvas);
        
        if(mTileArray != null)
        	drawWinOrLose(canvas);
    }
    
    private void drawWinOrLose(Canvas canvas)
    {
    	if(mode == MODE_WIN)
    		canvas.drawBitmap(mTileArray[WIN], 0, 0, paint);
    	else if(mode == MODE_LOSE)
    		canvas.drawBitmap(mTileArray[LOSE], 0, 0, paint);
    	
    	if(mode == MODE_LOSE)
    		Log.d("GameEvent", "Drawing X");
    }
    
    public void setMode(int newMode)
    {
    	mode = newMode;
    }

    
    /**
     * Simple class containing two integer values and a comparison function.
     * There's probably something I should use instead, but this was quick and
     * easy to build.
     * 
     */
    public class Coordinate {
        public int x;
        public int y;

        public Coordinate(int newX, int newY) {
            x = newX;
            y = newY;
        }

        public boolean equals(Coordinate other) {
            if (x == other.x && y == other.y) {
                return true;
            }
            return false;
        }

        @Override
        public String toString() {
            return "Coordinate: [" + x + "," + y + "]";
        }
    }


	public int getScore() {
		return 12;
	}

	public void addTouchPoint(int tileX, int tileY) {
		touchTrail.add(new Coordinate(tileX, tileY));
	}

    
}
